package com.bocloud.cmp.driver.providers.vmware;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.bocloud.cmp.driver.providers.MonitorDriver;
import com.bocloud.cmp.model.MonitorCategoryModel;
import com.bocloud.cmp.model.MonitorModel;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.utils.DateTool;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.vmware.vim25.PerfCounterInfo;
import com.vmware.vim25.PerfEntityMetric;
import com.vmware.vim25.PerfEntityMetricBase;
import com.vmware.vim25.PerfMetricId;
import com.vmware.vim25.PerfMetricIntSeries;
import com.vmware.vim25.PerfMetricSeries;
import com.vmware.vim25.PerfQuerySpec;
import com.vmware.vim25.PerfSampleInfo;
import com.vmware.vim25.mo.InventoryNavigator;
import com.vmware.vim25.mo.ManagedEntity;
import com.vmware.vim25.mo.PerformanceManager;

/**
 * vmware性能数据接口实现类
 * 
 * @author weiwei
 *
 */
public class VmwareMonitorDriver extends VmwareDriver implements MonitorDriver {

	private static Logger logger = LoggerFactory.getLogger(VmwareMonitorDriver.class);

	public VmwareMonitorDriver() {
		super();
	}

	/**
	 * @param endpoint
	 * @param username
	 * @param password
	 */
	public VmwareMonitorDriver(String endpoint, String username, String password) {
		super(endpoint, username, password);
	}

	@Override
	public BsmResult query(String time, String name, String category, String type) {
		try {
			PerformanceManager perfManager = this.getServiceInstance().getPerformanceManager();
			Map<String, Integer> counterMap = Maps.newHashMap();// 存放所有的counter名称以及对应的id
			PerfCounterInfo[] counterInfos = perfManager.getPerfCounter();
			for (PerfCounterInfo perfCounterInfo : counterInfos) {
				String key = perfCounterInfo.getGroupInfo().getKey() + "." + perfCounterInfo.getNameInfo().getKey()
						+ "." + perfCounterInfo.getRollupType().toString().toUpperCase();
				counterMap.put(key, perfCounterInfo.getKey());
			}
			ManagedEntity entity = null;
			if (category.equals("HostSystem")) {
				entity = new InventoryNavigator(this.getRootFolder()).searchManagedEntity("HostSystem", name);
			} else if (category.equals("VirtualMachine")) {
				entity = new InventoryNavigator(this.getRootFolder()).searchManagedEntity("VirtualMachine", name);
			} else {
				return new BsmResult(false, "暂不支持查看该类型对象性能数据");
			}
			if (null == entity) {
				return new BsmResult(false, "不存在该对象");
			}

			Integer interval = 20;
			time = time.trim();
			if (time.equals("REAL")) {
				interval = 20;
			} else if (time.equals("DAY")) {
				interval = 300;
			} else if (time.equals("WEEK")) {
				interval = 1800;
			} else if (time.equals("MONTH")) {
				interval = 7200;
			}

			int counterId = 0;
			type = type.trim();
			if (type.equals("CPU")) {
				// 获取每一个宿主机下的cpu.usagemhz.AVERAGE、mem.usage.AVERAGE、disk.usage.AVERAGE
				counterId = counterMap.get("cpu.usage.AVERAGE");// cpu.usagemhz.AVERAGE对应的counterId
			} else if (type.equals("MEM")) {
				// 获取宿主机下的内存数据
				counterId = counterMap.get("mem.usage.AVERAGE");
			} else if (type.equals("DISK")) {
				// 获取宿主机下的disk性能数据
				counterId = counterMap.get("disk.usage.AVERAGE");
			}
			List<String> keys = Lists.newArrayList();
			List<MonitorCategoryModel> models = Lists.newArrayList();
			getMonitorValue(counterId, interval, perfManager, entity, keys, models, type);
			MonitorModel monitorModel = new MonitorModel(keys, models);
			if (models.size() == 0) {
				return new BsmResult(false, "暂无数据");
			}
			return new BsmResult(true, monitorModel, "查询成功");
		} catch (Exception e) {
			logger.error("query performance failure:", e);
			return new BsmResult(false, "查询失败");
		} finally {
			this.getServiceInstance().getServerConnection().logout();
		}
	}

	private void getMonitorValue(Integer counterId, Integer timeInterval, PerformanceManager perfManager,
			ManagedEntity entity, List<String> keys, List<MonitorCategoryModel> models, String type) throws Exception {
		ArrayList<PerfMetricId> perfMetricIds = Lists.newArrayList();
		PerfMetricId[] queryAvailablePerfMetric = perfManager.queryAvailablePerfMetric(entity, null, null,
				timeInterval);
		if (null != queryAvailablePerfMetric) {
			for (PerfMetricId perfMetricId : queryAvailablePerfMetric) {
				if (counterId == perfMetricId.getCounterId()) {
					perfMetricIds.add(perfMetricId);
				}
			}
		}
		PerfMetricId[] pmis = perfMetricIds.toArray(new PerfMetricId[perfMetricIds.size()]);
		PerfQuerySpec qSpec = new PerfQuerySpec();
		qSpec.setEntity(entity.getMOR());
		qSpec.setMetricId(pmis);
		qSpec.setIntervalId(timeInterval);
		PerfEntityMetricBase[] perEntityMetrics = perfManager.queryPerf(new PerfQuerySpec[] { qSpec });
		if (null == perEntityMetrics) {
			return;
		}
		for (PerfEntityMetricBase perfEntityMetricBase : perEntityMetrics) {
			PerfEntityMetric pem = (PerfEntityMetric) perfEntityMetricBase;
			PerfSampleInfo[] samplerInfos = pem.getSampleInfo();// 保存有性能值对应的时间点
			if (null != samplerInfos) {
				for (PerfSampleInfo perfSampleInfo : samplerInfos) {
					keys.add(DateTool.formatTime(perfSampleInfo.getTimestamp().getTime()));
				}
			}
			PerfMetricSeries[] mertricSeries = pem.getValue();
			if (null != mertricSeries) {
				for (PerfMetricSeries perfMetricSeries : mertricSeries) {
					PerfMetricIntSeries metricIntSeries = (PerfMetricIntSeries) perfMetricSeries;
					long[] values = metricIntSeries.getValue();// 获取到的性能值
					if (null != values) {
						List<String> perfValues = Lists.newArrayList();
						for (long value : values) {
							if(value < 0){
								perfValues.add("0");
							}else{
								perfValues.add(String.valueOf(value));
							}
						}
						if (StringUtils.isEmpty(metricIntSeries.getId().getInstance())) {
							models.add(new MonitorCategoryModel(type, perfValues));
						} else {
							models.add(new MonitorCategoryModel(type + "-" + metricIntSeries.getId().getInstance(),
									perfValues));
						}
					}
				}
			}
		}
	}

}
